#pragma once

#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <math.h>
#include <stdio.h>
#include <iostream>
#define LINE_DETAIL 1;
#define FLAG 0;
using namespace std;

//===============================================================================
class Line_para{
	double l;
public:	
/*			// group of variables converted from global ones	
	int TH;
	int sTH;
	int CNTHa,CNTHb;
	int TH_LINEMATCH = 2;
	int sCNTHa, sCNTHb;
	int count_entire = 1;
	char filename[50], savenamea[50], savenameb[50];
	IplImage *src_c,*src_d,*src,*dst,*color_dst;
	CvMemStorage *storage = cvCreateMemStorage(0);
//	CvSeq *lines;
	CvFont textfont;
	int Muma[255][2];
	const int NOP = 6;
	CvPoint mouse[NOP];
	int click_count = 0;
	int messenger = 0;
*/
	IplImage *src;
	double k[255];
	double ave_i;
	CvSeq *lines;
	CvPoint *line;			// Line starting and ending point
	CvPoint Center[255];		// Line location (from *line)			// ????? cannot use "CvPoint *Center" to declare which makes more sense, will cause reading violation.
	CvPoint Van_point_v;		// Vanishing Point
	CvPoint *line_cor[255];			// line_corr: corresponded lines with two cvpoints (may introduce error there) with line_cor[i][1] representing 1st point [i][2] representing 2nd
	double line_cord[255][2][2];		// the more precise version of line_cor
	double left[255];
	double right[255];
	double sideA[255];
	double sideB[255];
    CvPoint *line1[255];
//	CvVector double line_func[255][3]; // eitehr CvVector line_func[255] (each vecto be 3*1) or double 
//	vector<double> line_funcv[255];
	double line_func[255][3];
	CvPoint intersection_hv[255];
//    CvPoint line2[255][2];
//	double *sideA;
//	double *sideB;
	double Length[255];
	int Corr[255];
	double match_index[255];
//	double ComputeLength(CvPoint *line);
	void ComputeLength(CvPoint *line, int i);
	void ComputeLeft(CvPoint *line, int i);
	void ComputeRight(CvPoint *line, int i);
	void ComputeSideA(CvPoint *line, int i);
	void ComputeSideB(CvPoint *line, int i);
	void ComputeAveI(IplImage *src);
	double IntP(double x, double y);
	int Bound(double x);
//	void ComputeMatchIndex(CvPoint *line, CvSeq *lines, int i);
};

// to be moved to lines.cpp trying to avoid error message by including lines.h in my_vlinebasedrestimator.h
void Line_para::ComputeAveI(IplImage *src){
	Line_para::ave_i = 0;
	for(int i = 0; i < src->height; i++){
		for(int j = 0; j < src->width; j++){
			Line_para::ave_i += (double)((uchar)src->imageData[i*src->widthStep + j]/(double)(src->width*src->height));
		}
	}
//	cout << "Average I"<< Line_para::ave_i<<endl;
}

double Line_para::IntP(double x, double y){		// Bilinear Interporlation.
	double value;
	double rx,ry,vi0,vi1;
	rx = x - floor(x); ry = y - floor(y);
	int x_f = floor(x),y_f = floor(y), x_c = ceil(x), y_c = ceil(y);
	if(Bound(y_f*src->widthStep + x_f)&&Bound((y_f*src->widthStep + x_c))&&Bound(y_c*src->widthStep + x_f)&&Bound(y_c*src->widthStep + x_c)){
//	if((src->imageData[y_f*src->widthStep + x_f])&&(src->imageData[y_f*src->widthStep + x_c]) &&(src->imageData[y_c*src->widthStep + x_f]) &&(src->imageData[y_c*src->widthStep + x_c])){
		vi0 = rx*(uchar)src->imageData[y_f*src->widthStep + x_f] + (1-rx)*(uchar)src->imageData[y_f*src->widthStep + x_c];
		vi1 = rx*(uchar)src->imageData[y_c*src->widthStep + x_f] + (1-rx)*(uchar)src->imageData[y_c*src->widthStep + x_c];
//	vi0 = rx*src->imageData[(int)floor(y)*src->widthStep + (int)floor(x)] + (1-rx)*src->imageData[(int)floor(y)*src->widthStep + (int)ceil(x)];
//	vi1 = rx*src->imageData[(int)ceil(y)*src->widthStep + (int)floor(x)] + (1-rx)*src->imageData[(int)ceil(y)*src->widthStep + (int)ceil(x)];
	value = ry*vi1 + (1 - ry)*vi0;
	return value;
	}
	else
		return 0;
}

int Line_para::Bound(double x){
	int bound = ((x >= 0)&&( x <= 239*src->widthStep + 319));
	return bound;
	cout << "bound" << x << " " << bound << endl;
}

//double Line_para::ComputeLength(CvPoint *line){
//	l = sqrt(pow(line[0].x - line[1].x,2.0) + pow(line[1].x - line[1].y, 2.0));
//	return l;
//}
void Line_para::ComputeLength(CvPoint *line,int i){
	Line_para::Length[i] = sqrt(pow((line[0].x - line[1].x),2.0) + pow((line[0].y - line[1].y), 2.0));
}

void Line_para::ComputeSideA(CvPoint *line, int i){
	int x,y;
	double x_p,y_p;
//	sideA = new double;
	sideA[i] = 0;
	line = (CvPoint*)cvGetSeqElem(lines,i);
	k[i] = (line[1].x - line[0].x)?((double)(line[1].y - line[0].y)/(line[1].x - line[0].x)):999999;
	for(int j = min(line[0].y,line[1].y); j <= max(line[0].y,line[1].y); j++){
		x = (j-line[0].y)/k[i] + line[0].x; y = j;
		if((x>=0)&&(x<src->width)&&(y>=0)&&(y<src->height)){
			for(int s = 1; s < 4; s++){		//  3 5 7 on both sides;
				x_p = sqrt(pow((2*s+1),2.0)/(1+pow((-1/k[i]),2.0)));	y_p = (-1.0/k[i])*x_p;
//				sideA[i] += IntP(x + x_p,y + y_p)/(double)((2*s + 1)*Line_para::Length[i]*(Line_para::ave_i/255)) ;
				sideA[i] += IntP(x + x_p,y + y_p)/(double)((2*s + 1)*Line_para::Length[i]);
			}
		}
	}
}

void Line_para::ComputeSideB(CvPoint *line, int i){
	int x,y;
	double x_p,y_p;
	sideB[i] = 0;
	line = (CvPoint*)cvGetSeqElem(lines,i);
	k[i] = (line[1].x - line[0].x)?((double)(line[1].y - line[0].y)/(line[1].x - line[0].x)):999999;
	for(int j = min(line[0].y,line[1].y); j <= max(line[0].y,line[1].y); j++){
		x = (j-line[0].y)/k[i] + line[0].x; y = j;
		if((x>=0)&&(x<src->width)&&(y>=0)&&(y<src->height)){
			for(int s = 1; s < 4; s++){		// 357 on both sides;
				x_p = -sqrt(pow((2*s+1),2.0)/(1+pow((-1/k[i]),2.0)));	y_p = (-1.0/k[i])*x_p;			// x_p get +/- sqrt() is two sides of the same line
//				sideB[i] += IntP(x + x_p,y + y_p)/(double)((2*s + 1)*Line_para::Length[i]*(Line_para::ave_i/255)) ;
				sideB[i] += IntP(x + x_p,y + y_p)/(double)((2*s + 1)*Line_para::Length[i]);
			}
		}
	}
}


void Line_para::ComputeLeft(CvPoint *line, int i){
	int x,y;
//	for(int i = 0; i < lines->total; i++){
	left[i] = 0;
	line = (CvPoint*)cvGetSeqElem(lines,i);
	k[i] = (line[1].x - line[0].x)?((double)(line[1].y - line[0].y)/(line[1].x - line[0].x)):999999;
	for(int j = min(line[0].y,line[1].y); j <= max(line[0].y,line[1].y); j++){
		x = (j-line[0].y)/k[i] + line[0].x; y = j;
		if((x>=0)&&(x<src->width)&&(y>=0)&&(y<src->height))
			left[i] += (uchar)src->imageData[y*src->widthStep + x - 1];
//				left[i] += src->imageData[j*src->widthStep + (int)((j-line[0].y)/k + line[0].x)-1];
	}
//	}
}
void Line_para::ComputeRight(CvPoint *line, int i){
	int x,y;
//	for(int i = 0; i < lines->total; i++){
	right[i] = 0;
	line = (CvPoint*)cvGetSeqElem(lines,i);
	k[i] = (line[1].x - line[0].x)?((double)(line[1].y - line[0].y)/(line[1].x - line[0].x)):999999;
//		k = (line[1].y - line[0].y)/(line[1].x - line[0].x);
	for(int j = min(line[0].y,line[1].y); j <= max(line[0].y,line[1].y); j++){
		x = (j-line[0].y)/k[i] + line[0].x; y = j;
		if((x>=0)&&(x<src->width)&&(y>=0)&&(y<src->height))
			right[i] += (uchar)src->imageData[y*src->widthStep + x + 1];
//				right[i] += src->imageData[j*src->widthStep + (int)((j-line[0].y)/k + line[0].x)+1];
	}
//	}
}



int TH1,TH2;  // 100 - 50
int sTH1, sTH2;		//for window
int CNTH1a, CNTH1b, CNTH2a, CNTH2b;
int TH_LINEMATCH = 2;			// line matching searches width/TH_L * height/TH_L range for candidates, the larger, the stricter
int sCNTH1a, sCNTH1b, sCNTH2a, sCNTH2b;
int count_entire = 1;		// 2 for displaying entire number of lines   0 for displaying line index     1 for both
char filename1[50], filename2[50], savename1[50], savename2[50],savename3[50], savename4[50];
Line_para para1, para2;
IplImage *src1_c, *src2_c, *src1_d, *src2_d, *src1, *src2, *dst1, *dst2, *color_dst1, *color_dst2;
CvMemStorage *storage1 = cvCreateMemStorage(0), *storage2 = cvCreateMemStorage(0);;
CvSeq *lines1 = 0, *lines2 = 0;
CvFont textfont;
int Muma[255][2];
const int NOP = 6;
CvPoint mouse1[NOP],mouse2[NOP];
int click_count1 = 0, click_count2 = 0;
//char haha[10] = "haha";
int messenger = 0;



//extern int TH1;